package jp.ac.u_tokyo.dch.action.conv;

import java.util.List;

import jp.ac.u_tokyo.dch.core.db.DBConnection;
import jp.ac.u_tokyo.dch.core.exceptions.DBException;
import jp.ac.u_tokyo.dch.dao.common.SeqenceGenerator;
import jp.ac.u_tokyo.dch.dao.data.DataDao;
import jp.ac.u_tokyo.dch.dao.schema.DataSchemaDao;
import jp.ac.u_tokyo.dch.model.DataGroup;
import jp.ac.u_tokyo.dch.model.SchemaGroup;
import jp.ac.u_tokyo.dch.model.db.DataSchema;
import jp.ac.u_tokyo.dch.model.db.DataSchemaDetail;
import jp.ac.u_tokyo.dch.model.output.Attribute;
import jp.ac.u_tokyo.dch.model.output.XmlComposite;
import jp.ac.u_tokyo.dch.model.output.XmlData;
import jp.ac.u_tokyo.dch.model.xml.DisplayDefine;
import jp.ac.u_tokyo.dch.service.ConvService;
import jp.ac.u_tokyo.dch.service.DaoServiceAware;
import jp.ac.u_tokyo.dch.service.DataSchemaService;
import jp.ac.u_tokyo.dch.service.FrontService;
import jp.ac.u_tokyo.dch.service.Transaction;
import jp.ac.u_tokyo.dch.util.common.CommonUtil;
import jp.ac.u_tokyo.dch.util.common.DisplayUtil;
import jp.ac.u_tokyo.dch.util.common.ModoruUtil;
import jp.ac.u_tokyo.dch.view.Constants;
import jp.ac.u_tokyo.dch.view.conv.ConvView;

import org.apache.commons.lang.xwork.StringUtils;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

/**
 * @version 1.1
 */
public class ConvAction extends ActionSupport implements ModelDriven<ConvView>,
		DaoServiceAware {

	/**
	 * シリアル番号
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * スキーマグループリスト
	 */
	private List<SchemaGroup> schemaGroupList;

	private String rowNum;
	/**
	 * 画面定義
	 */
	private DisplayDefine define;

	/** カスタム */
	private List<DataSchemaDetail> customSchemaDetailList;

	private DataSchema dataSchema;
	/**
	 * 画面モデル
	 */
	private ConvView view = new ConvView();

	/** XML表示オブジェクト */
	private XmlComposite xmlDisObj;

	private List<DataGroup> dataGroupList;

	/**
	 * DBコネクションオブジェクト
	 */
	private DBConnection dbConnection = null;

	/**
	 * 初期化処理
	 *
	 * @return 結果
	 * @throws Exception
	 *             例外
	 */
	public String init() throws Exception {

		ModoruUtil.modoruProcess(ServletActionContext.getRequest(),
				"/outputconv/main", "");

		FrontService frontService = new FrontService(dbConnection);

		schemaGroupList = frontService.getMetaDataPatternList();

		return SUCCESS;
	}

	public String output() throws Exception {

		ConvService convService = new ConvService(dbConnection);
		DataSchemaDao dataSchemaDao = new DataSchemaDao(dbConnection);
		DataDao dataDao = new DataDao(dbConnection);
		SchemaGroup schemaGroup = dataSchemaDao.selectMetaDataPattern(view
				.getKeySchemaid());

		if (convService.selectXmlDataForOutput(schemaGroup.getLv1Schemaid()).isEmpty()) {

			addFieldError("id",getText("noreadyxmloutput", new String[] { "作成機関の概要名称" }));
		}
		if (convService.selectXmlDataForOutput(schemaGroup.getLv2Schemaid()).isEmpty()) {

			addFieldError("id",
					getText("noreadyxmloutput", new String[] { "目録データ概要名称" }));
		}
		if (convService.selectXmlDataForOutput(schemaGroup.getLv3Schemaid()).isEmpty()) {

			addFieldError("id", getText("noreadyxmloutput", new String[] { "資料群全体名称" }));
		}
		if (convService.selectXmlDataForOutput(schemaGroup.getLv4Schemaid()).isEmpty()) {

			addFieldError("id", getText("noreadyxmloutput", new String[] { "サブフォンド名称" }));
		}
		if (convService.selectXmlDataForOutput(schemaGroup.getLv5Schemaid()).isEmpty()) {

			addFieldError("id", getText("noreadyxmloutput", new String[] { "シリーズ名称" }));
		}
		if (convService.selectXmlDataForOutput(schemaGroup.getLv6Schemaid()).isEmpty()) {

			addFieldError("id", getText("noreadyxmloutput", new String[] { "アイテム 名称" }));
		}

		if (hasErrors()) {
			FrontService frontService = new FrontService(dbConnection);
			schemaGroupList = frontService.getMetaDataPatternList();
			return ERROR;
		}

		dataGroupList = dataDao.selectDataGroupByL3(view.getKeySchemaid());

		return SUCCESS;
	}

	/**
	 * 出力フォーマットを追加する
	 *
	 * @return
	 * @throws Exception
	 */
	public String add() throws Exception {

		ConvService convService = new ConvService(dbConnection);

		viewInit();

		String schemaid = view.getKeySchemaid();

		view.setXmlObjList(convService.selectXmlData(schemaid));

		xmlDisObj = view.xmlObjListToXmlDisObj();

		return SUCCESS;
	}

	/**
	 * 子ノードを追加する
	 *
	 * @return
	 * @throws Exception
	 */
	public String addChild() throws Exception {

		SeqenceGenerator generator = new SeqenceGenerator(dbConnection);

		int size = view.getXmlObjList().size();

		XmlData xmlData = new XmlData();
		xmlData.setIndex(String.valueOf(size));
		xmlData.setTagId(String.valueOf(generator.getSequence(SeqenceGenerator.TAG_SEQ)));
		xmlData.setOyaTagId(view.getTargetTagId());
		xmlData.setTagName("");
		xmlData.setLevel(String.valueOf(Constants.MAX_LEVEL));
		xmlData.setType(view.getInsertType());

		view.getXmlObjList().add(xmlData);

		xmlDisObj = view.xmlObjListToXmlDisObj();

		return SUCCESS;
	}

	/**
	 * 子ノードを削除する
	 *
	 * @return
	 * @throws Exception
	 */
	public String delChild() throws Exception {

		view.delete();
		xmlDisObj = view.xmlObjListToXmlDisObj();

		return SUCCESS;
	}

	public String orderChange() throws Exception {

		view.orderChange();
		xmlDisObj = view.xmlObjListToXmlDisObj();
		return SUCCESS;
	}

	public String addAttr() throws Exception {

		view.addAttr();

		xmlDisObj = view.xmlObjListToXmlDisObj();

		return SUCCESS;
	}

	public String delAttr() throws Exception {

		view.delAttr();

		xmlDisObj = view.xmlObjListToXmlDisObj();

		return SUCCESS;
	}

	@Transaction
	public String execute() throws Exception {

		ConvService convService = new ConvService(dbConnection);

		int insertTagCnt = 0;

		for (XmlData xmlData : view.getXmlObjList()) {

			if (Constants.TAG_TYPE_TEXT.equals(xmlData.getType())
					&& StringUtils.isEmpty(xmlData.getTagName())) {
				addFieldError(xmlData.getTagId(), getText("requiredstring", new String[] { "タグ名" }));
			}

			if (CommonUtil.isContansXmlChar(xmlData.getTagName())) {
				addFieldError(xmlData.getTagId(), getText("xmlescapemozierror", new String[] { "タグ名" }));
			}

//			if (CommonUtil.isContansXmlChar(xmlData.getText())) {
//				addFieldError("id", getText("xmlescapemozierror", new String[] { "テキスト" }));
//			}

			for (Attribute attr : xmlData.getAttrList()) {
				if (CommonUtil.isContansXmlChar(attr.getName())) {
					addFieldError(xmlData.getTagId(), getText("xmlescapemozierror", new String[] { "属性名" }));
				}
				if (CommonUtil.isContansXmlCharSpaceYes(attr.getValue())) {
					addFieldError(xmlData.getTagId(), getText("xmlescapemozierror", new String[] { "属性値" }));
				}
			}

			if (Constants.TAG_TYPE_CHILD.equals(xmlData.getType())) {

				insertTagCnt++;
			}
		}

		if (Constants.LV3_SORT.equals(view.getSort())
				|| Constants.LV4_SORT.equals(view.getSort())
				|| Constants.LV5_SORT.equals(view.getSort())) {

			if (insertTagCnt != 1) {

				addFieldError("id", getText("inserttagerror"));
			}
		}

		if (hasErrors()) {
			viewInit();
			xmlDisObj = view.xmlObjListToXmlDisObj();
			return ERROR;
		}

		convService.insert(view);

		return SUCCESS;
	}

	/**
	 * 画面に表示する項目を取得する
	 *
	 * @param service
	 *            フロントサービス
	 * @throws DBException
	 */
	private void viewInit() throws DBException {

		DataSchemaService dataSchemaService = new DataSchemaService(
				dbConnection);

		dataSchema = dataSchemaService.findSchema(view.getKeySchemaid());

		view.setSort(dataSchema.getSort());

		define = DisplayUtil.getItemDefine(dataSchema.getSort());

		if (Constants.LV1_SORT.equals(dataSchema.getSort())) {

			rowNum = "10";

		} else if (Constants.LV2_SORT.equals(dataSchema.getSort())) {

			rowNum = "14";

		} else if (Constants.LV3_SORT.equals(dataSchema.getSort())) {

			rowNum = "56";

		} else if (Constants.LV4_SORT.equals(dataSchema.getSort())) {

			rowNum = "23";

		} else if (Constants.LV5_SORT.equals(dataSchema.getSort())) {

			rowNum = "14";

		} else if (Constants.LV6_SORT.equals(dataSchema.getSort())) {

			rowNum = "91";
		}

		customSchemaDetailList = dataSchemaService.getSchemaDetailList(
				view.getKeySchemaid(), "1");
	}

	@Override
	public void setDBConnection(DBConnection con) {
		dbConnection = con;

	}

	/**
	 *
	 * @return 画面名を返す
	 */
	public String getGamenName() {
		return getText("outputmenu_" + dataSchema.getSort());
	}

	public List<SchemaGroup> getSchemaGroupList() {
		return schemaGroupList;
	}

	public void setSchemaGroupList(List<SchemaGroup> schemaGroupList) {
		this.schemaGroupList = schemaGroupList;
	}

	public XmlComposite getXmlDisObj() {
		return xmlDisObj;
	}

	public void setXmlDisObj(XmlComposite xmlDisObj) {
		this.xmlDisObj = xmlDisObj;
	}

	public DisplayDefine getDefine() {
		return define;
	}

	public void setDefine(DisplayDefine define) {
		this.define = define;
	}

	public DataSchema getDataSchema() {
		return dataSchema;
	}

	public void setDataSchema(DataSchema dataSchema) {
		this.dataSchema = dataSchema;
	}

	public String getRowNum() {
		return rowNum;
	}

	public void setRowNum(String rowNum) {
		this.rowNum = rowNum;
	}

	public List<DataSchemaDetail> getCustomSchemaDetailList() {
		return customSchemaDetailList;
	}

	public void setCustomSchemaDetailList(
			List<DataSchemaDetail> customSchemaDetailList) {
		this.customSchemaDetailList = customSchemaDetailList;
	}

	public List<DataGroup> getDataGroupList() {
		return dataGroupList;
	}

	public void setDataGroupList(List<DataGroup> dataGroupList) {
		this.dataGroupList = dataGroupList;
	}

	@Override
	public ConvView getModel() {
		return view;
	}

}
